#ifndef MIIO_COMMAND_H_
#define MIIO_COMMAND_H_

//#include "miio_ota_mcu.h"
//#include "miio_ota_app.h"
//#include "miio_instance.h"
#include "common/list.h"
#include "miio_user_api.h"
//#include "miio_arch.h"

#define MCMD_OLD_PROTO_ADAPT				1
#define MCMD_COMMAND_LEN_MAX				(900)
#define MCMD_COMMAND_ARG_MAX				(64)
#define MCMD_JSON_BUF_SIZE					(1024)

#define CMDID_MASK                          0xff
#define CMDTYPE_MASK                        0xff00
#define CMD_COMBINE(cid , tid)              ((cid & CMDID_MASK) | ((tid << 8) & CMDTYPE_MASK))
#define CMD_CID(value)                      ((value & CMDID_MASK))
#define CMD_TID(value)                      ((value & CMDTYPE_MASK) >> 8)

//Cmd ID for network binding 
#define  UART_CMD_NETBIND                   0x01
#define  UART_CMD_NETBIND_OOBREQ            CMD_COMBINE(0x01, UART_CMD_NETBIND)
#define  UART_CMD_NETBIND_DEVINFO           CMD_COMBINE(0x02, UART_CMD_NETBIND)
#define  UART_CMD_NETBIND_NETINFO           CMD_COMBINE(0x03, UART_CMD_NETBIND)
#define  UART_CMD_NETBIND_DEVCERT           CMD_COMBINE(0x04, UART_CMD_NETBIND)
#define  UART_CMD_NETBIND_MANUCERT          CMD_COMBINE(0x05, UART_CMD_NETBIND)
#define  UART_CMD_NETBIND_SIGN              CMD_COMBINE(0x06, UART_CMD_NETBIND)
#define  UART_CMD_NETBIND_NETSTATUS         CMD_COMBINE(0x07, UART_CMD_NETBIND)

//Cmd ID for remote unlock
#define  UART_CMD_LOGIN_REQ                 CMD_COMBINE(0x20, UART_CMD_NETBIND)
#define  UART_CMD_LOGIN_RSP                 CMD_COMBINE(0x21, UART_CMD_NETBIND)
#define  UART_CMD_LOGIN_CFM                 CMD_COMBINE(0x22, UART_CMD_NETBIND)
#define  UART_CMD_LOGIN_CFM_RSP             CMD_COMBINE(0x23, UART_CMD_NETBIND)

//Cmd ID for ota 
#define  UART_CMD_OTA                       0x04
#define  UART_CMD_OTA_INFO                  CMD_COMBINE(0x01, UART_CMD_OTA)
#define  UART_CMD_OTA_DATA                  CMD_COMBINE(0x02, UART_CMD_OTA)
#define  UART_CMD_OTA_STATUS                CMD_COMBINE(0x03, UART_CMD_OTA)
#define  UART_CMD_OTA_REBOOT                CMD_COMBINE(0x04, UART_CMD_OTA)

//Cmd ID for spec
#define  UART_CMD_SPEC                      0x05
#define  UART_CMD_SPEC_SET                  CMD_COMBINE(0x01, UART_CMD_SPEC)
#define  UART_CMD_SPEC_SET_RSP              CMD_COMBINE(0x02, UART_CMD_SPEC)
#define  UART_CMD_SPEC_GET                  CMD_COMBINE(0x03, UART_CMD_SPEC)
#define  UART_CMD_SPEC_GET_RSP              CMD_COMBINE(0x04, UART_CMD_SPEC)
#define  UART_CMD_SPEC_ACTION_IN            CMD_COMBINE(0x05, UART_CMD_SPEC)
#define  UART_CMD_SPEC_ACTION_OUT           CMD_COMBINE(0x06, UART_CMD_SPEC)
#define  UART_CMD_SPEC_PROPS_CHANGED        CMD_COMBINE(0x07, UART_CMD_SPEC)
#define  UART_CMD_SPEC_EVENT_OCCURED        CMD_COMBINE(0x08, UART_CMD_SPEC)
#define  UART_CMD_SPEC_BLE_EVENT_CB         CMD_COMBINE(0x0A, UART_CMD_SPEC)

#define  UART_CMD_HEADER                    "LU"
#define  UART_CMD_VERSION                   0x01

//Destination  Address
#define  UART_CMD_DA_BLE                    0x01
#define  UART_CMD_DA_HOSTMCU                0x02
#define  UART_CMD_DA_SLAVEMCU               0x03
#define  UART_CMD_DA_WIFI                   0x04
#define  UART_CMD_DA_MEDIAMCU               0x05
//Source Address
#define  UART_CMD_SA                        UART_CMD_DA_BLE

//Header+Version+Source Address+Destination  Address+Payload Length+Cmd ID+Cmd Length+CRC16
#define  UART_CMD_MIN_LENGTH                13 

typedef void* (*fp_mcmd_io_create_t)(void *arg);
typedef int (*fp_mcmd_io_block_in_t)(void *handle, char *buf, int buf_size, int idle_timeout_ms);
typedef void (*fp_mcmd_io_block_quit_t)(void *handle);
typedef int (*fp_mcmd_io_out_t)(void *handle, const char *buf, int buf_size);
typedef void (*fp_mcmd_io_destroy_t)(void **handle);
typedef int (*fp_mcmd_io_echo_t)(void *handle, const char *arg);
typedef int (*fp_mcmd_io_int_byte_t)(void *handle, unsigned char *c, int timeout_ms);
typedef void (*fp_mcmd_io_out_byte_t)(void *handle, unsigned char c);

typedef struct{
	void *handle;
	fp_mcmd_io_create_t 	create;
	fp_mcmd_io_block_in_t 	block_in;
	fp_mcmd_io_block_quit_t block_quit;
	fp_mcmd_io_out_t		out;
	fp_mcmd_io_destroy_t	destroy;
	fp_mcmd_io_echo_t		echo;
	fp_mcmd_io_int_byte_t	in_byte;
	fp_mcmd_io_out_byte_t	out_byte;
}mcmd_io_if_t;

typedef struct {
    int run_state;
	mcmd_io_if_t io;
	char *command_buf;
	int command_buf_size;
}mcmd_uart_t;

int mcmd_uart_init(mcmd_uart_t* mcmd_uart, mcmd_io_if_t *pio);
void mcmd_uart_deinit(mcmd_uart_t* mcmd_uart);
int mcmd_uart_send(mcmd_uart_t* mcmd_uart, int cmd, char *params, int length);
int mcmd_uart_handle(mcmd_uart_t* mcmd_uart, char *params, int length);

void* uart_create(void *arg);
void uart_destroy(void **handle);
int uart_out(void *handle, const char *buf, int vCount);
void uart_out_byte(void *handle, unsigned char c);
int uart_block_in(void *handle, char *buf, int buf_size, int idle_timeout_ms);
void uart_block_quit(void *handle);
int uart_in_byte(void *handle, unsigned char *c, int timeout_ms);

int mcmd_spec_init(void);
mible_status_t do_get_properties(uint8_t *pdata, uint16_t ilen, uint16_t tid);
mible_status_t do_set_properties(uint8_t *pdata, uint16_t ilen, uint16_t tid);
mible_status_t do_action(uint8_t *pdata, uint16_t ilen, uint16_t tid);
int cb_oncmd_spec_get_rsp(mcmd_uart_t* mcmd_uart, char *params, int length);
int cb_oncmd_spec_set_rsp(mcmd_uart_t* mcmd_uart, char *params, int length);
int cb_oncmd_spec_action_out(mcmd_uart_t* mcmd_uart, char *params, int length);
int cb_oncmd_spec_props_changed(mcmd_uart_t* mcmd_uart, char *params, int length);
int cb_oncmd_spec_event_occured(mcmd_uart_t* mcmd_uart, char *params, int length);

#endif /* MIIO_COMMAND_H_ */
